using Microsoft.EntityFrameworkCore;
using DaoHang.Data;
using DaoHang.Models;
using HtmlAgilityPack;

namespace DaoHang.Services
{
    /// <summary>
    /// 网站服务实现类，处理网站相关的业务逻辑
    /// </summary>
    public class WebsiteService : IWebsiteService
    {
        private readonly ApplicationDbContext context;
        private readonly HttpClient httpClient;
        private readonly ILogger<WebsiteService> logger;
        private readonly IIconService iconService;

        /// <summary>
        /// 构造函数，注入依赖服务
        /// </summary>
        /// <param name="context">数据库上下文</param>
        /// <param name="httpClient">HTTP客户端</param>
        /// <param name="logger">日志记录器</param>
        /// <param name="iconService">图标服务</param>
        public WebsiteService(ApplicationDbContext context, HttpClient httpClient, ILogger<WebsiteService> logger, IIconService iconService)
        {
            this.context = context;
            this.httpClient = httpClient;
            this.logger = logger;
            this.iconService = iconService;
        }

        /// <summary>
        /// 获取所有网站列表，按分类和排序展示
        /// </summary>
        /// <returns>网站列表</returns>
        public async Task<List<Website>> GetAllWebsitesAsync()
        {
            try
            {
                // 查询所有网站，包含分类信息，按访问次数降序排序，然后按分类排序和创建时间排序
                return await context.Websites
                    .Include(w => w.Category)
                    .OrderByDescending(w => w.VisitCount)
                    .ThenBy(w => w.Category.SortOrder)
                    .ThenByDescending(w => w.CreateTime)
                    .ToListAsync();
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "获取所有网站列表时发生错误");
                throw;
            }
        }

        /// <summary>
        /// 根据分类ID获取网站列表
        /// </summary>
        /// <param name="categoryId">分类ID</param>
        /// <returns>指定分类下的网站列表</returns>
        public async Task<List<Website>> GetWebsitesByCategoryAsync(int categoryId)
        {
            try
            {
                return await context.Websites
                    .Include(w => w.Category)
                    .Where(w => w.CategoryId == categoryId)
                    .OrderByDescending(w => w.VisitCount)
                    .ThenByDescending(w => w.CreateTime)
                    .ToListAsync();
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "根据分类ID {CategoryId} 获取网站列表时发生错误", categoryId);
                throw;
            }
        }

        /// <summary>
        /// 根据ID获取网站详情
        /// </summary>
        /// <param name="id">网站ID</param>
        /// <returns>网站信息</returns>
        public async Task<Website?> GetWebsiteByIdAsync(int id)
        {
            try
            {
                return await context.Websites
                    .Include(w => w.Category)
                    .FirstOrDefaultAsync(w => w.Id == id);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "根据ID {Id} 获取网站详情时发生错误", id);
                throw;
            }
        }

        /// <summary>
        /// 添加新网站
        /// </summary>
        /// <param name="website">网站信息</param>
        /// <returns>添加的网站</returns>
        public async Task<Website> AddWebsiteAsync(Website website)
        {
            try
            {
                // 自动下载并保存图标到本地
                if (string.IsNullOrEmpty(website.IconUrl))
                {
                    logger.LogInformation("开始为网站 {Name} 自动下载图标", website.Name);
                    website.IconUrl = await iconService.DetectAndDownloadIconAsync(website.Url, website.Name);
                    logger.LogInformation("网站 {Name} 图标设置为: {IconUrl}", website.Name, website.IconUrl);
                }
                else
                {
                    // 如果用户提供了图标URL，也下载到本地
                    logger.LogInformation("开始为网站 {Name} 下载用户指定的图标: {IconUrl}", website.Name, website.IconUrl);
                    var localIconPath = await iconService.DownloadAndSaveIconAsync(website.IconUrl, website.Name);
                    if (!string.IsNullOrEmpty(localIconPath))
                    {
                        website.IconUrl = localIconPath;
                        logger.LogInformation("网站 {Name} 图标已保存到本地: {LocalPath}", website.Name, localIconPath);
                    }
                    else
                    {
                        logger.LogWarning("网站 {Name} 指定图标下载失败，尝试自动检测", website.Name);
                        website.IconUrl = await iconService.DetectAndDownloadIconAsync(website.Url, website.Name);
                    }
                }

                // 如果没有指定名称，尝试自动获取标题
                if (string.IsNullOrEmpty(website.Name))
                {
                    var title = await GetWebsiteTitleAsync(website.Url);
                    if (!string.IsNullOrEmpty(title))
                    {
                        website.Name = title;
                    }
                }

                website.CreateTime = DateTime.Now;
                
                context.Websites.Add(website);
                await context.SaveChangesAsync();
                
                logger.LogInformation("成功添加网站: {Name} ({Url}), 图标: {IconUrl}", website.Name, website.Url, website.IconUrl);
                return website;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "添加网站时发生错误: {Name} ({Url})", website.Name, website.Url);
                throw;
            }
        }

        /// <summary>
        /// 快速添加新网站（不下载图标）
        /// </summary>
        /// <param name="website">网站信息</param>
        /// <returns>添加的网站</returns>
        public async Task<Website> AddWebsiteQuickAsync(Website website)
        {
            try
            {
                // 如果没有图标URL，设置为默认图标路径
                if (string.IsNullOrEmpty(website.IconUrl))
                {
                    website.IconUrl = iconService.GetDefaultIconPath();
                }

                // 如果没有指定名称，尝试自动获取标题（快速方式）
                if (string.IsNullOrEmpty(website.Name))
                {
                    // 在快速模式下，如果没有名称就使用URL作为临时名称
                    website.Name = website.Url;
                }

                website.CreateTime = DateTime.Now;
                
                context.Websites.Add(website);
                await context.SaveChangesAsync();
                
                logger.LogInformation("快速添加网站成功: {Name} ({Url}), 默认图标: {IconUrl}", website.Name, website.Url, website.IconUrl);
                return website;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "快速添加网站时发生错误: {Name} ({Url})", website.Name, website.Url);
                throw;
            }
        }

        /// <summary>
        /// 创建新网站
        /// </summary>
        /// <param name="website">网站信息</param>
        /// <returns>是否创建成功</returns>
        public async Task<bool> CreateWebsiteAsync(Website website)
        {
            try
            {
                var result = await AddWebsiteAsync(website);
                return result != null;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 更新网站信息
        /// </summary>
        /// <param name="website">网站信息</param>
        /// <returns>更新的网站</returns>
        public async Task<Website> UpdateWebsiteAsync(Website website)
        {
            try
            {
                var existingWebsite = await context.Websites.FindAsync(website.Id);
                if (existingWebsite == null)
                {
                    throw new InvalidOperationException($"未找到ID为 {website.Id} 的网站");
                }

                // 更新属性
                existingWebsite.Name = website.Name;
                existingWebsite.Url = website.Url;
                existingWebsite.Description = website.Description;
                existingWebsite.IconUrl = website.IconUrl;
                existingWebsite.CategoryId = website.CategoryId;
                existingWebsite.SortOrder = website.SortOrder;

                await context.SaveChangesAsync();
                
                logger.LogInformation("成功更新网站: {Name} ({Url})", website.Name, website.Url);
                return existingWebsite;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "更新网站时发生错误: ID {Id}", website.Id);
                throw;
            }
        }

        /// <summary>
        /// 删除网站
        /// </summary>
        /// <param name="id">网站ID</param>
        /// <returns>删除是否成功</returns>
        public async Task<bool> DeleteWebsiteAsync(int id)
        {
            try
            {
                var website = await context.Websites.FindAsync(id);
                if (website == null)
                {
                    return false;
                }

                context.Websites.Remove(website);
                await context.SaveChangesAsync();
                
                logger.LogInformation("成功删除网站: {Name} (ID: {Id})", website.Name, id);
                return true;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "删除网站时发生错误: ID {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 自动获取网站图标
        /// </summary>
        /// <param name="url">网站URL</param>
        /// <returns>图标URL</returns>
        public async Task<string?> GetWebsiteIconAsync(string url)
        {
            try
            {
                if (string.IsNullOrEmpty(url))
                    return null;

                // 确保URL有协议前缀，优先使用HTTPS
                if (!url.StartsWith("http://") && !url.StartsWith("https://"))
                {
                    url = "https://" + url;
                }

                var uri = new Uri(url);
                var baseUrl = $"{uri.Scheme}://{uri.Host}";

                // 确保baseUrl使用HTTPS以避免混合内容问题
                baseUrl = EnsureHttpsUrl(baseUrl);

                // 尝试多种获取图标的方式
                var iconUrls = new[]
                {
                    $"{baseUrl}/favicon.ico",
                    $"{baseUrl}/favicon.png", 
                    $"{baseUrl}/apple-touch-icon.png",
                    $"{baseUrl}/apple-touch-icon-precomposed.png"
                };

                // 首先尝试解析HTML中的icon链接
                try
                {
                    var response = await httpClient.GetStringAsync(url);
                    var doc = new HtmlDocument();
                    doc.LoadHtml(response);

                    var iconLinks = doc.DocumentNode
                        .SelectNodes("//link[@rel='icon' or @rel='shortcut icon' or @rel='apple-touch-icon']");

                    if (iconLinks != null)
                    {
                        foreach (var link in iconLinks)
                        {
                            var href = link.GetAttributeValue("href", "");
                            if (!string.IsNullOrEmpty(href))
                            {
                                string iconUrl;
                                if (href.StartsWith("//"))
                                    iconUrl = "https:" + href; // 强制使用HTTPS
                                else if (href.StartsWith("/"))
                                    iconUrl = baseUrl + href;
                                else if (href.StartsWith("http"))
                                    iconUrl = EnsureHttpsUrl(href); // 确保使用HTTPS
                                else
                                    iconUrl = baseUrl + "/" + href;
                                
                                return iconUrl;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    logger.LogWarning(ex, "解析HTML获取图标失败，尝试默认路径: {Url}", url);
                }

                // 尝试默认图标路径
                foreach (var iconUrl in iconUrls)
                {
                    try
                    {
                        var request = new HttpRequestMessage(HttpMethod.Head, iconUrl);
                        var response = await httpClient.SendAsync(request);
                        if (response.IsSuccessStatusCode)
                        {
                            return iconUrl;
                        }
                    }
                    catch
                    {
                        // 继续尝试下一个路径
                    }
                }

                // 如果都失败了，返回默认favicon路径
                return $"{baseUrl}/favicon.ico";
            }
            catch (Exception ex)
            {
                logger.LogWarning(ex, "获取网站图标失败: {Url}", url);
                return null;
            }
        }

        /// <summary>
        /// 确保URL使用HTTPS协议，避免混合内容问题
        /// </summary>
        /// <param name="url">原始URL</param>
        /// <returns>HTTPS URL</returns>
        private static string EnsureHttpsUrl(string url)
        {
            if (string.IsNullOrEmpty(url))
                return url;

            // 如果是HTTP协议，转换为HTTPS
            if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
            {
                return "https://" + url.Substring(7);
            }

            // 如果是协议相对URL，添加HTTPS
            if (url.StartsWith("//"))
            {
                return "https:" + url;
            }

            return url;
        }

        /// <summary>
        /// 获取网站标题
        /// </summary>
        /// <param name="url">网站URL</param>
        /// <returns>网站标题</returns>
        public async Task<string?> GetWebsiteTitleAsync(string url)
        {
            try
            {
                if (string.IsNullOrEmpty(url))
                    return null;

                // 确保URL有协议前缀，优先使用HTTPS
                if (!url.StartsWith("http://") && !url.StartsWith("https://"))
                {
                    url = "https://" + url;
                }

                var response = await httpClient.GetStringAsync(url);
                var doc = new HtmlDocument();
                doc.LoadHtml(response);

                var titleNode = doc.DocumentNode.SelectSingleNode("//title");
                return titleNode?.InnerText?.Trim();
            }
            catch (Exception ex)
            {
                logger.LogWarning(ex, "获取网站标题失败: {Url}", url);
                return null;
            }
        }

        /// <summary>
        /// 增加网站访问次数
        /// </summary>
        /// <param name="id">网站ID</param>
        /// <returns>是否增加成功</returns>
        public async Task<bool> IncrementVisitCountAsync(int id)
        {
            try
            {
                var website = await context.Websites.FindAsync(id);
                if (website == null)
                {
                    return false;
                }

                website.VisitCount++;
                await context.SaveChangesAsync();
                
                logger.LogInformation("增加网站访问次数: {Name} (ID: {Id}), 当前访问次数: {Count}", website.Name, id, website.VisitCount);
                return true;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "增加网站访问次数时发生错误: ID {Id}", id);
                return false;
            }
        }

        /// <summary>
        /// 后台异步更新网站图标
        /// </summary>
        /// <param name="websiteUrl">网站URL</param>
        /// <returns>是否更新成功</returns>
        public async Task<bool> UpdateWebsiteIconAsync(string websiteUrl)
        {
            try
            {
                logger.LogInformation("开始后台更新网站图标: {WebsiteUrl}", websiteUrl);

                // 查找对应的网站
                var website = await context.Websites.FirstOrDefaultAsync(w => w.Url == websiteUrl);
                if (website == null)
                {
                    logger.LogWarning("未找到对应网站: {WebsiteUrl}", websiteUrl);
                    return false;
                }

                // 下载并保存图标
                var newIconPath = await iconService.DetectAndDownloadIconAsync(website.Url, website.Name);
                
                // 更新数据库中的图标路径
                website.IconUrl = newIconPath;
                context.Websites.Update(website);
                await context.SaveChangesAsync();

                logger.LogInformation("网站图标后台更新成功: {Name} -> {IconPath}", website.Name, newIconPath);
                return true;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "后台更新网站图标时发生错误: {WebsiteUrl}", websiteUrl);
                return false;
            }
        }
    }
} 